// ===============================================================================================
// 
// Driver section; not part of the architecture, but is there to test the components of the game
// and to react to user's actions.
//
// =============================================================================================== 

#include "Character.h"
#include "WarriorCharacter.h"
#include "NonPlayerCharacter.h"
#include "PositionKeeper.h"
#include "PlayerCharacter.h"
#include "Space.h"
#include "SentinelBridgeSpace.h"
#include "Map.h"
#include <iostream>
#include <memory>
#include <conio.h>

using namespace std;

// ===============================================================================================
// 
// Outputs the map contents on the screen
//
// =============================================================================================== 
void drawMap(talisman_map::Map& iMap)
{
	cout << "OUTER REGION:\n\n";

	shared_ptr<talisman_map::Space> wIter = iMap.getOuterRegionStartSpace();
	unsigned int i = 0;
	do 
	{
		cout << "\t" << ++i << ". " << wIter->getDescription().c_str() << endl;
		wIter = wIter->getNextSpace();
	} 
	while (wIter != iMap.getOuterRegionStartSpace());

	cout << "\n\n";

	cout << "MIDDLE REGION:\n\n";

	wIter = iMap.getMiddleRegionStartSpace();
	i = 0;
	do 
	{
		cout << "\t" << ++i << ". " << wIter->getDescription().c_str() << endl;
		wIter = wIter->getNextSpace();
	} 
	while (wIter != iMap.getMiddleRegionStartSpace());

	cout << "\n\n";

	cout << "INNER REGION:\n\n";

	wIter = iMap.getInnerRegionStartSpace();
	i = 0;
	do 
	{
		cout << "\t" << ++i << ". " << wIter->getDescription().c_str() << endl;
		wIter = wIter->getNextSpace();
	} 
	while (wIter != iMap.getInnerRegionStartSpace());

	cout << "\n\n";
}

// ===============================================================================================
// 
// Halts the program until user presses any key
//
// =============================================================================================== 
void pressAnyKey(void)
{
	cout << "Press any key...\n\n";
	_getch();
}

// ===============================================================================================
// 
// Draws one cell with its description (ASCII-art)
//
// =============================================================================================== 
void drawOneCell(char *iText, PositionKeeper& iPositionKeeper, shared_ptr<PlayerCharacter> iPlayer)
{
	string wCellDescription = iPositionKeeper.getCharacterLocation(iPlayer)->getDescription();
	cout << iText << "\n";
	cout << "+" << string(wCellDescription.length()+2, '-').c_str() << "+\n";
	cout << "| " << wCellDescription.c_str() << " |\n";
	cout << "+" << string(wCellDescription.length()+2, '-').c_str() << "+\n";
}

void main()
{
	// Artificially nested scope to test descructors
	{
		cout << "Welcome to Yuri's Talisman simulator!\n\n";

		cout << "This program will simulate two parts of the game: Character properties and movement on the map. \n\n 1. The first part will demonstrate that a character's strength and craft are dependent both on his nominal values as well as those added by his/her followers.\n\n";
		cout << "2. The second part will first demonstrate how the character can move on the map and then allow you to control him by a series of commands to move to any space, in any region, but only where it's possible to go from each particular cell.\n\n";

		pressAnyKey();

		//	CREATING THE MAIN CHARACTER
		shared_ptr<WarriorCharacter> wPlayer = make_shared<WarriorCharacter>();

		cout << "Creating a character 'WarriorCharacter'; \n\tname=" << wPlayer->getName().c_str() << "\n\tstrength=" << wPlayer->getStrengthValue() << "\n\tcraft=" << wPlayer->getCraftValue() << "." << endl;

		pressAnyKey();

		cout << "Let's say we added 1 strength counter to the character.\n" << endl;

		pressAnyKey();

		wPlayer->setStrengthCounter(wPlayer->getStrengthCounter() + 1);

		// CREATING A FOLLOWER
		string wName = "Woodpecker Woody";
		string wDescription = "It's a woodpecker from space!";
		int wStrengthValue = 1;
		int wCraftValue = 6;

		cout << "Creating a follower character 'NonPlayerCharacter'; \n\tname=" << wName.c_str() << "\n\tstrength=" << wStrengthValue << "\n\tcraft=" << wCraftValue << "." << endl;

		pressAnyKey();

		shared_ptr<NonPlayerCharacter> wFollower = make_shared<NonPlayerCharacter>(wName, wDescription, wStrengthValue, wCraftValue);

		cout << "Adding the new character as a follower of the player...\n\n";

		pressAnyKey();

		shared_ptr<NonPlayerCharacter> wFollowerPointer;
		wPlayer->addFollower(wFollower);

		cout << "The new strength and craft of the player, with the follower and 1 extra strength counter counted: \n\tstrength=" << wPlayer->getTotalCharacterStrength() << "\n\tcraft=" << wPlayer->getTotalCharacterCraft() << endl;

		pressAnyKey();

		talisman_map::Map wMap;
		PositionKeeper wPositionKeeper;
		wPositionKeeper.placeCharacter(wPlayer, wMap);

		cout << "\nAlright! Time for the real fun! Here is the map we're going to walk on. Press any key to see the map!" << endl;

		pressAnyKey();

		drawMap(wMap);

		pressAnyKey();

		drawOneCell("We started traveling on the map! Our first space has the following description", wPositionKeeper, wPlayer);

		pressAnyKey();

		cout << "We're making a step of 1 now, to the next cell." << endl;

		wPositionKeeper.advanceCharacter(wPlayer, 1);

		drawOneCell("Here is the next space:", wPositionKeeper, wPlayer);

		pressAnyKey();

		wPositionKeeper.advanceCharacter(wPlayer,3);


		drawOneCell("Now, let's assume the dice rolls 3 and we'll skip over two cells.\nThe next cell is:", wPositionKeeper, wPlayer);

		pressAnyKey();

		wPositionKeeper.movebackCharacter(wPlayer, 2);

		drawOneCell("Woa, I'm not into fighting dragons, just yet..let's move back a couple of steps!\nWe're at cell:", wPositionKeeper, wPlayer);

		pressAnyKey();

		wPositionKeeper.advanceCharacter(wPlayer, 5);

		cout << "We've rolled 5 and now we're at:\n" << wPositionKeeper.getCharacterLocation(wPlayer)->getDescription().c_str() << endl;

		drawOneCell("We've rolled 5 and now we're at:", wPositionKeeper, wPlayer);

		cout << "\nWould you like to take the bridge? (y/n): ";

		char wResponse[10];

		cin >> wResponse;

		if (strcmp(wResponse, "y") ==0)
		{
			wPositionKeeper.takeTheBridge(wPlayer);
			drawOneCell("Mmm, let's see where we are:", wPositionKeeper, wPlayer);
			pressAnyKey();
		}
		else
		{
			cout << "Well, alright then!\n\n";
			pressAnyKey();
		}

		cout << "Ok, now you can walk on your own! Enter: \n\t'f' to go one step forward \n\t'b' to go one step backward \n\t's' to take the sentinel bridge (if possible)\n\t'p' to take the portal of power (if possible)\n\t'q' to quit\n\n";

		do
		{
			cout << "Enter command: ";
			cin >> wResponse;

			if (strcmp(wResponse, "f") == 0)
				wPositionKeeper.advanceCharacter(wPlayer, 1);
			else if (strcmp(wResponse, "b") == 0)
				wPositionKeeper.movebackCharacter(wPlayer, 1);
			else if (strcmp(wResponse, "s") == 0)
				wPositionKeeper.takeTheBridge(wPlayer);
			else if (strcmp(wResponse, "p") == 0)
				wPositionKeeper.useThePortal(wPlayer);
			else
				cout << "Incorrect input!\n\n";

			drawOneCell("You've attempted to move, your new position: ", wPositionKeeper, wPlayer);
		}
		while (strcmp(wResponse, "q") != 0);

		cout << "\n\nThank you for using Yuri's Talisman simulator.\n\n";

		pressAnyKey();
	}
}